package com.talent.study.nio;

import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author: hszhou
 * @Date: 2025/4/25 10:42
 * @Description: 必须描述类做什么事情, 实现什么功能
 */
@Slf4j
public class TimerServer {


    public static void main(String[] args) {




     new Thread(   new MultiplexerTimeServer(8080)).start();
    }


    public static class MultiplexerTimeServer implements Runnable{


        private Selector selector;

        private ServerSocketChannel serverSocketChannel;

        private volatile  boolean stop;
        public MultiplexerTimeServer(int port){

            try{
                selector = Selector.open();
                serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.configureBlocking(false);

                serverSocketChannel.bind(new InetSocketAddress(port));
                serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                log.info("the time server is start in port [{}]",port);
            }catch (Exception e){
                e.printStackTrace();
                log.error("错误");
            }
        }

        public void stop(){
            this.stop = true;
        }
        @Override
        public void run() {

            while (!stop){
                try{

                    selector.select(1000);

                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();

                    SelectionKey key = null;

                    while (iterator.hasNext()){
                        key = iterator.next();
                        iterator.remove();
                        try{
                            handlerInput(key);
                        }catch (Exception e){
                         if(key!=null){
                             key.cancel();
                             if (key.channel()!=null) {
                                 key.channel().close();
                             }
                         }
                        }
                    }
                }catch (Throwable e){
                    e.printStackTrace();
                }
            }

            if(selector!=null){
                try{
                    selector.close();
                }catch (Exception e){
                    e.printStackTrace();
                    log.error("错误");
                }
            }
        }

        private void handlerInput(SelectionKey key) throws Exception{

            if(key.isValid()){

                if(key.isAcceptable()){
                    ServerSocketChannel channel =(ServerSocketChannel) key.channel();

                    log.info("收到连接");
                    SocketChannel accept = channel.accept();

                    log.info("收到客户端【{}】的连接",accept);
                    accept.configureBlocking(false);
                    accept.register(selector,SelectionKey.OP_READ);
                }
                if(key.isReadable()){
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    int readBytes = channel.read(readBuffer);
                    if(readBytes>0){
                        readBuffer.flip();
                        byte[] bytes = new byte[readBuffer.remaining()];
                        readBuffer.get(bytes);
                        String body = new String(bytes,"UTF-8");
                        log.info("the time server receive order : {}", body);
                        doWrite(channel,"hello "+body);
                    }else if(readBytes<0){
                        key.cancel();
                        serverSocketChannel.close();
                    }else{

                    }
                }
            }
        }
        private void doWrite(SocketChannel channel,String response) throws Exception{
            if(response!=null&&response.trim().length()>0){
                byte[] bytes = response.getBytes();
                ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
                writeBuffer.put(bytes);
                writeBuffer.flip();
                channel.write(writeBuffer);
            }
        }
    }
}
